//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.TridentUtilities
{
    using System;
    using System.Runtime.InteropServices;
    using System.Windows;
    using System.Windows.Media;

    /// <summary>
    /// Holds unmanaged code calls that gets the mouse position wrt a UIElement.
    /// </summary>
    public static class SafeNativeMethods
    {
        /// <summary>
        /// Represents the point object.
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        private struct Win32Point
        {
            /// <summary>
            /// The horizontal coordinate.
            /// </summary>
            public Int32 X;

            /// <summary>
            /// The vertical coordinate.
            /// </summary>
            public Int32 Y;
        };

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetCursorPos(ref Win32Point pt);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ScreenToClient(IntPtr hwnd, ref Win32Point pt);

        /// <summary>
        /// Gets the mouse position.
        /// </summary>
        /// <param name="relativeTo">
        /// Relative to what Visual object.
        /// </param>
        /// <returns>
        /// The mouse position.
        /// </returns>
        public static Point GetMousePosition(Visual relativeTo)
        {
            Win32Point mouse = new Win32Point();
            GetCursorPos(ref mouse);

            System.Windows.Interop.HwndSource presentationSource =
                (System.Windows.Interop.HwndSource)PresentationSource.FromVisual(relativeTo);

            ScreenToClient(presentationSource.Handle, ref mouse);

            GeneralTransform transform = relativeTo.TransformToAncestor(presentationSource.RootVisual);

            Point offset = transform.Transform(new Point(0, 0));

            return new Point(mouse.X - offset.X, mouse.Y - offset.Y);
        }
    }
}